package blacklistoperationlogic

import (
	"context"
	"dfx_cmdb/cmdb-blacklist-rpc/internal/svc"
	cmdbblacklist "dfx_cmdb/models/cmdb-blacklist"
	"fmt"
	"strings"
	"time"

	"github.com/zeromicro/go-zero/core/logc"
)

func QueryClickHouseHaproxyTopIp(ctx context.Context, s *svc.ServiceContext) ([]cmdbblacklist.HaproxyErrorLogView, error) {
	var haproxyErrorLogView []cmdbblacklist.HaproxyErrorLogView

	// 构建基础查询
	query := s.CDB.WithContext(ctx).
		Model(&cmdbblacklist.HaproxyErrorLogView{}).
		Where("five_min_bucket >= now() - INTERVAL 15 MINUTE")

	// 查询IP忽略规则
	ignoreVal := &cmdbblacklist.BlacklistIgnoreRule{}
	err := s.PDB.WithContext(ctx).
		Where("ignore_type = ?", "ip").
		First(&ignoreVal).Error

	// 如果查询成功且规则启用，则添加IP过滤条件
	if err == nil && ignoreVal.Enable != nil && *ignoreVal.Enable && ignoreVal.IgnoreVal != "" {
		ips := strings.Split(ignoreVal.IgnoreVal, ",")
		if len(ips) > 0 {
			// 去除空字符串
			validIps := make([]string, 0, len(ips))
			for _, ip := range ips {
				if trimmedIp := strings.TrimSpace(ip); trimmedIp != "" {
					validIps = append(validIps, trimmedIp)
				}
			}
			if len(validIps) > 0 {
				query = query.Where("client_ip NOT IN ?", validIps)
				logc.Infof(ctx, "已应用IP忽略规则，过滤 %d 个IP", len(validIps))
			}
		}
	} else if err != nil {
		// 忽略规则查询失败，记录日志但继续执行
		logc.Infof(ctx, "查询IP忽略规则失败: %v，将不应用过滤规则", err)
	}

	// 执行最终查询
	err = query.
		Order("error_count DESC").
		Limit(s.Config.Ipblacklist.MaxIpNum).
		Find(&haproxyErrorLogView).Error

	if err != nil {
		logc.Errorf(ctx, "查询ClickHouse失败: %v", err)
		return nil, err
	}

	logc.Infof(ctx, "查询到 %d 条haproxy错误日志", len(haproxyErrorLogView))
	return haproxyErrorLogView, nil
}

func RedisSetHaproxyBlacklist(ctx context.Context, s *svc.ServiceContext, haproxyErrorLogView []cmdbblacklist.HaproxyErrorLogView) error {
	if len(haproxyErrorLogView) == 0 {
		return nil
	}

	// 使用 Pipeline 批量写入
	pipe := s.RC.Pipeline()
	for _, haproxyErrorLog := range haproxyErrorLogView {
		key := fmt.Sprintf("blacklist:haproxy:%s:%s", haproxyErrorLog.Backend, haproxyErrorLog.ClientIp)
		pipe.Set(ctx, key, 1, time.Duration(s.Config.Ipblacklist.Timeout)*time.Hour)
	}

	// 执行所有命令
	_, err := pipe.Exec(ctx)
	if err != nil {
		logc.Errorf(ctx, "批量写入Redis失败: %v", err)
		return err
	}

	logc.Infof(ctx, "成功批量写入 %d 条haproxy黑名单到Redis", len(haproxyErrorLogView))
	return nil
}
